import { expect } from '@jest/globals';
import fse from 'fs-extra';
import JSON5 from 'json5';

import { getJson5Obj } from '../../../../src/utils/json-util';
import { initExecuteCommand, runHvigorAsync, runHvigorFailAsync } from '../../common/common';
import { buildServiceCard } from '../../plugins/common-fun';
import {
  AbilityType,
  APIType,
  APIVersion,
  CaseLevel,
  LanguageType,
  ModuleTemplateType,
  RuntimeOSType,
  SDKType,
} from '../../plugins/project-builder/models/constants';
import { TestCaseBuilder } from '../../plugins/task-builder/task-case-builder';
import { ProjectBuildOption, TestCaseFun } from '../../plugins/task-builder/test-case';
import { TestTaskOptionBuilder } from '../../plugins/task-builder/test-task-option';

const projectBuilderOption: ProjectBuildOption = {
  template: {
    sdk: SDKType.Single,
    runtimeOS: RuntimeOSType.HarmonyOS,
    apiVersion: APIVersion.API10,
    apiType: APIType.STAGE,
    language: LanguageType.ArkTs,
    abilityType: AbilityType.Application,
    entryTemplateType: ModuleTemplateType.EmptyAbility,
  },
  modulesOption: [ModuleTemplateType.StaticLibrary],
};

const writeFormExtensionAbility = async (moduleJsonPath: string, moduleJson: any, metadata: { name: string; resource: string }[] | undefined) => {
  moduleJson.module.extensionAbilities = [
    {
      name: 'EntryFormAbility',
      srcEntry: './ets/entryformability/EntryFormAbility.ets',
      label: '$string:EntryFormAbility_label',
      description: '$string:EntryFormAbility_desc',
      type: 'form',
      metadata,
    },
  ];
  await fse.writeFile(moduleJsonPath, JSON5.stringify(moduleJson, null, 2), 'utf-8');
};

const testFun: TestCaseFun = async (project, taskConfig, record) => {
  const projectRootPath = project.projectRootPath();
  const command = initExecuteCommand({
    mode: 'module',
    product: 'default',
    tasks: 'assembleHap',
  });
  const module = project.getModule('entry');
  const modulePath = module.moduleRootPath();
  await buildServiceCard(modulePath);
  const moduleJsonPath = module.moduleModuleJsonPath();
  const moduleJson = getJson5Obj(moduleJsonPath);

  await writeFormExtensionAbility(moduleJsonPath, moduleJson, undefined);
  const result = await runHvigorFailAsync(projectRootPath, command);
  record.addStep('form extensionAbility 配置，缺少metadata字段', result);
  expect(result.stderr).toContain('The metadata field in FormExtensionAbility cannot be left blank or as an empty array.');

  await writeFormExtensionAbility(moduleJsonPath, moduleJson, []);
  const result1 = await runHvigorFailAsync(projectRootPath, command);
  record.addStep('form extensionAbility 配置，metadata字段为空数组', result1);
  expect(result1.stderr).toContain('The metadata field in FormExtensionAbility cannot be left blank or as an empty array.');

  await writeFormExtensionAbility(moduleJsonPath, moduleJson, [
    {
      name: 'ohos.extension.test',
      resource: '$profile:form_config',
    },
  ]);
  const result2 = await runHvigorFailAsync(projectRootPath, command);
  record.addStep('form extensionAbility 配置，metadata字段中没有配置name为ohos.extension.form的对象', result2);
  expect(result2.stderr).toContain(
    'In FormExtensionAbility, ' +
      "metadata must contain an object with its name set to 'ohos.extension.form' and resource set to a second-level resource reference.",
  );

  await writeFormExtensionAbility(moduleJsonPath, moduleJson, [
    {
      name: 'ohos.extension.form',
      resource: '$profile:form_config',
    },
  ]);
  const result3 = await runHvigorAsync(projectRootPath, command);
  record.addStep('form extensionAbility 配置，metadata配置ohos.extension.form', result3);
  expect(result3.stdout).toContain('Finished :entry:default@PreBuild');
  expect(result3.stdout).toContain('BUILD SUCCESSFUL');
};

TestCaseBuilder.builder()
  .caseName('FormExtensionAbility')
  .description(
    '校验module.json5下module.extensionAbilities.metadata字段，FormExtensionAbility中metadata字段不能缺省、也不能为空数组且 必须要存在一个name为‘ohos.extension.form’的对象值',
  )
  .projectBuilderOption(projectBuilderOption)
  .taskConfig(TestTaskOptionBuilder.builder().caseLevel(CaseLevel.L2).build())
  .testFun(testFun)
  .load();
